package com.example.camera;

import android.app.AlertDialog;
import android.app.Dialog;
import android.content.Context;
import android.content.DialogInterface;
import android.content.res.AssetManager;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.Matrix;
import android.graphics.Paint;
import android.graphics.Rect;
import android.os.Bundle;
import android.os.Handler;
import android.os.Message;
import android.util.Log;
import android.util.Pair;
import android.util.Size;
import android.view.Gravity;
import android.view.LayoutInflater;
import android.view.MotionEvent;
import android.view.View;
import android.view.ViewGroup;
import android.view.Window;
import android.view.WindowManager;
import android.widget.Button;
import android.widget.EditText;
import android.widget.ImageButton;
import android.widget.ImageView;
import android.widget.LinearLayout;
import android.widget.RadioButton;
import android.widget.RadioGroup;
import android.widget.TextView;
import android.widget.Toast;

import androidx.fragment.app.Fragment;

import com.example.camera.tflite.Classifier;
import com.example.camera.tflite.TFLiteObjectDetectionSSDAPIModel;
import com.google.gson.Gson;

import java.io.IOException;
import java.io.InputStream;
import java.net.InetAddress;
import java.net.SocketAddress;
import java.net.URI;
import java.net.URISyntaxException;
import java.nio.ByteBuffer;
import java.util.ArrayList;
import java.util.List;
import java.util.Timer;
import java.util.TimerTask;

import android.graphics.Point;

import org.java_websocket.client.WebSocketClient;
import org.java_websocket.handshake.ServerHandshake;
import org.opencv.android.OpenCVLoader;
import org.opencv.android.Utils;
import org.opencv.core.Mat;
import org.opencv.imgproc.Imgproc;

import org.opencv.tracking.Tracker;
import org.opencv.tracking.TrackerCSRT;
import org.opencv.tracking.TrackerKCF;
import org.opencv.tracking.TrackerMIL;
import org.opencv.tracking.TrackerMOSSE;
import org.opencv.tracking.TrackerMedianFlow;
import org.opencv.tracking.TrackerTLD;

import okhttp3.OkHttpClient;
import okhttp3.Request;
import okhttp3.Response;

public class Esp32CameraFragment extends Fragment{

    public enum STATE {
        STOP,
        RUN,
        PAUSE
    };

    enum Drawing{
        DRAWING,
        TRACKING,
        CLEAR,
    }

    final String TAG = "ExCameraFragment";

    private UDPSocket mUdpClient;
    private String mServerAddressBroadCast = "192.168.45.36";
    InetAddress mServerAddr;
    int mServerPort = 6868;
    final byte[] mRequestConnect      = new byte[]{'w','h','o','a','m','i'};
    final byte[] mRequestForward      = new byte[]{'f','o','r','w','a','r','d'};

    final byte[] mRequestBackward    = new byte[]{'b','a','c','k','w','a','r','d'};
    final byte[] mRequestLeft        = new byte[]{'l','e','f','t'};

    final byte[] mRequestRight       = new byte[]{'r','i','g','h','t'};

    final byte[] mRequestStop        = new byte[]{'s','t','o','p'};
    final byte[] mSpeedAdd = new byte[]{'s','p','a','d','d'};
    final byte[] mSpeedSub = new byte[]{'s','p','s','u','b'};
    final byte[] mRequestCamUp       = new byte[]{'1'};
    final byte[] mRequestCamDown     = new byte[]{'2'};
    final byte[] mRequestCamLeft     = new byte[]{'3'};
    final byte[] mRequestCamRight    = new byte[]{'4'};
    final byte[] mRequestCamStill    = new byte[]{'5'};
    final byte[] mLedOn = new byte[]{'l','e','d','o','n'};
    final byte[] mLedOff = new byte[]{'l','e','d','o','f','f'};
    final byte[] LaneTrackingOn = new byte[]{'l','a','n','e','o','n'};
    final byte[] ObjectTrackingOn = new byte[]{'o','b','j','e','c','t','o','n'};
    int count = 0;
    private Handler handler = new Handler();
    private Bitmap mBitmap;

    ImageView mServerImageView;
    Handler mHandler = new Handler();

    private WebSocketClient mWebSocketClient;
    private String mServerExactAddress;
    private boolean mInitStream = false;
    private boolean mInitTrackObj = false;
    private boolean mStream = false;
    private boolean mObjDet = false;
    private boolean mLed = false;
    private int speed = 40;
    private String Temp;
    private String Humi;
    private String Voc;
    private String Co2;
    ImageButton mBackMoveBtn;
    ImageButton mForMoveBtn;
    ImageButton mRightMoveBtn;
    ImageButton mLeftMoveBtn;
    VerticalText Tem_Text;
    VerticalText Hum_Text;
    VerticalText Voc_Text;
    VerticalText Co2_Text;

    private Classifier detectorSSD;
    private List<TFLiteObjectDetectionSSDAPIModel.Recognition> detectorSSDResult = new ArrayList<>();

    private final Size CamResolution = new Size(640, 480);

    private OverlayView mTrackingOverlay;
    private Bitmap mBitmapDebug;
    private boolean mProcessing = false;
    private Point[] mPoints = new Point[4];
    private Point mPointCircle = new Point();
    private int mRadiusCircle = 0;
    private Drawing mDrawing = Drawing.CLEAR;
    private boolean mTargetLocked = false;
    private Bitmap mBitmapGrab = null;

    private String mSelectedTracker = "None";
    private Tracker mTracker;
    private Mat mMatGrabInit;
    private Mat mMatGrab;
    private org.opencv.core.Rect2d mInitRectangle = null;

    private int mRadioIndex = 0;

    final String[] mRadioBtnNames = {
            "None",
            "ObjectTracking",
            "LaneTracking"
    };

    public void onWindowFocusChanged(){
        int testW = mTrackingOverlay.getWidth();
        int testH = mTrackingOverlay.getHeight();
//        mTrackingOverlay.setLayoutParams(new FrameLayout.LayoutParams(testW, CamResolution.getWidth()/CamResolution.getHeight()*testW));
//        mServerImageView.setLayoutParams(new FrameLayout.LayoutParams(testW, CamResolution.getWidth()/CamResolution.getHeight()*testW));
    }

    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);

        mUdpClient = new UDPSocket(12345);
        mUdpClient.runUdpServer();

        try {
            mServerAddr = InetAddress.getByName(mServerAddressBroadCast);
        }catch (Exception e){

        }

        AssetManager assetManager = getActivity().getAssets();
        if (MyConstants.DEBUG) {
            try {
                InputStream istr = assetManager.open("image1.jpg");
                Bitmap tmpBitmap = BitmapFactory.decodeStream(istr);
                mBitmapDebug = Bitmap.createScaledBitmap(tmpBitmap, CamResolution.getWidth(), CamResolution.getHeight(), false);
            } catch (IOException e) {
                // handle exception
            }
        }
        if (!OpenCVLoader.initDebug()) {
            Log.d(TAG, "Internal OpenCV library not found. Using OpenCV Manager for initialization");
            OpenCVLoader.initAsync(OpenCVLoader.OPENCV_VERSION_3_4_0, getActivity(), null);
        }
    }

    @Override
    public View onCreateView(LayoutInflater inflater, ViewGroup parent, Bundle savedInstanceState) {
        View rootView = inflater.inflate(R.layout.fragment_camera, parent, false);

        mServerImageView = (ImageView)rootView.findViewById(R.id.imageView);
        Timer mtimer=new Timer(true);
        TimerTask task = new TimerTask(){
            @Override
            public void run() {
                //your code
                Get();
                mHandler.sendEmptyMessage(1);
            }
        };
        mtimer.schedule(task, 1000, 500);//等待1秒后,执行一次，之后每隔0.5秒,再次执行
        mHandler = new Handler() {
            @Override
            public void handleMessage(Message msg){
                switch (msg.what){
                    case 1:
                        Voc_Text.setText(Voc);
                        Co2_Text.setText(Co2);
                        Tem_Text.setText(Temp);
                        Hum_Text.setText(Humi);
                        break;
                    default:break;
                }
            }
        };
        Tem_Text = rootView.findViewById(R.id.Temp_show);
        Hum_Text = rootView.findViewById(R.id.Humi_show);
        Voc_Text = rootView.findViewById(R.id.Voc_show);
        Co2_Text = rootView.findViewById(R.id.Co2_show);

        Button streamBtn = (Button) rootView.findViewById(R.id.streamBtn);
        streamBtn.setOnClickListener(new View.OnClickListener(){
            @Override
            public void onClick(View v){
                if (!mStream) {
                    showAdressDialog(getActivity());
                    try {
                        mServerAddr = InetAddress.getByName(mServerAddressBroadCast);
                    }catch (Exception e){

                    }
                    mUdpClient.sendBytes(mServerAddr, mServerPort, mRequestConnect);
                    Pair<SocketAddress, String> res = mUdpClient.getResponse();
                    int cnt = 3;
                    while (res.first == null && cnt > 0) {
                        res = mUdpClient.getResponse();
                        cnt--;
                    }
                    if (res.first != null) {
                        Log.d(TAG, res.first.toString() + ":" + res.second);
                        mServerExactAddress = res.first.toString().split(":")[0].replace("/","");
                        mStream = true;
                        connectWebSocket();
                        ((Button) getActivity().findViewById(R.id.streamBtn)).setBackgroundResource(R.drawable.my_button_bg_2);
                        ((Button) getActivity().findViewById(R.id.streamBtn)).setTextColor(Color.rgb(0,0,255));
                        try {
                            mServerAddr = InetAddress.getByName(mServerExactAddress);
                        }catch (Exception e){

                        }
                    }else{
                        Toast toast =
                                Toast.makeText(
                                        getActivity(), "Cannot connect to ESP32 Camera", Toast.LENGTH_LONG);
                        toast.setGravity(Gravity.CENTER, 0, 0);
                        toast.show();
                    }
                } else {
                    mStream = false;
                    mWebSocketClient.close();
                    ((Button) getActivity().findViewById(R.id.streamBtn)).setBackgroundResource(R.drawable.my_button_bg);
                    ((Button) getActivity().findViewById(R.id.streamBtn)).setTextColor(Color.rgb(255,255,255));
                }
            }
        });
//LED灯按键
        Button ledBtn = (Button) rootView.findViewById(R.id.ledBtn);
        ledBtn.setOnClickListener(new View.OnClickListener(){
            @Override
            public void onClick(View v){
                if (!mLed) {
                    mLed = true;
                    ((Button) getActivity().findViewById(R.id.ledBtn)).setBackgroundResource(R.drawable.my_button_bg_2);
                    ((Button) getActivity().findViewById(R.id.ledBtn)).setTextColor(Color.rgb(0,0,255));
                    mUdpClient.sendBytes(mServerAddr, mServerPort, mLedOn);
                }else{
                    mLed = false;
                    ((Button) getActivity().findViewById(R.id.ledBtn)).setBackgroundResource(R.drawable.my_button_bg);
                    ((Button) getActivity().findViewById(R.id.ledBtn)).setTextColor(Color.rgb(255,255,255));
                    mUdpClient.sendBytes(mServerAddr, mServerPort, mLedOff);
                }
            }
        });

        Button objFollowBtn = (Button) rootView.findViewById(R.id.objTrackBtn);
        objFollowBtn.setOnClickListener(new View.OnClickListener(){
            @Override
            public void onClick(View v){
                if(mTargetLocked==true){
                    Toast toast =
                            Toast.makeText(
                                    getActivity(), "Please touch with 2 fingers to release the tracking object first !", Toast.LENGTH_SHORT);
                    toast.show();
                    return;
                }
                trackingDlg();
            }
        });

        Button objDetBtn = (Button) rootView.findViewById(R.id.objDetBtn);
        objDetBtn.setOnClickListener(new View.OnClickListener(){
            @Override
            public void onClick(View v){
                if (!mObjDet) {
                    ((Button) getActivity().findViewById(R.id.objDetBtn)).setBackgroundResource(R.drawable.my_button_bg_2);
                    ((Button) getActivity().findViewById(R.id.objDetBtn)).setTextColor(Color.rgb(0,0,255));
                } else {
                    ((Button) getActivity().findViewById(R.id.objDetBtn)).setBackgroundResource(R.drawable.my_button_bg);
                    ((Button) getActivity().findViewById(R.id.objDetBtn)).setTextColor(Color.rgb(255,255,255));
                }
                mObjDet = !mObjDet;
            }
        });

//加速减速按钮
        Button suBtn = (Button) rootView.findViewById(R.id.speedsubBtn);
        Button saBtn = (Button) rootView.findViewById(R.id.speedaddBtn);
        saBtn.setOnClickListener(new View.OnClickListener(){
            @Override
            public void onClick(View v){
                if(speed <= 100) speed += 20;

                saBtn.setText(speed + " ++");
                suBtn.setText(speed + " --");
                mUdpClient.sendBytes(mServerAddr, mServerPort, mSpeedAdd);
            }
        });

        suBtn.setOnClickListener(new View.OnClickListener(){
            @Override
            public void onClick(View v){
                if(speed > 20) speed -= 20;

                saBtn.setText(speed + " ++");
                suBtn.setText(speed + " --");
                mUdpClient.sendBytes(mServerAddr, mServerPort, mSpeedSub);
            }
        });
//前后左右按钮
        ImageButton.OnTouchListener listener = new ImageButton.OnTouchListener() {
            @Override
            public boolean onTouch(View arg0, MotionEvent event){
                if(event.getAction() == MotionEvent.ACTION_DOWN) {
                    if (((ImageButton) arg0).getId() == R.id.forwardMoveBtn) {
                        ((ImageButton)arg0).setImageResource(R.drawable.ic_btn_forward_on);
                        mUdpClient.sendBytes(mServerAddr, mServerPort, mRequestForward);
                    } else if (((ImageButton) arg0).getId() == R.id.backwardMoveBtn) {
                        ((ImageButton)arg0).setImageResource(R.drawable.ic_btn_backward_on);
                        mUdpClient.sendBytes(mServerAddr, mServerPort, mRequestBackward);
                    } else if (((ImageButton) arg0).getId() == R.id.leftMoveBtn) {
                        ((ImageButton)arg0).setImageResource(R.drawable.ic_btn_left_on);
                        mUdpClient.sendBytes(mServerAddr, mServerPort, mRequestLeft);
                    } else if (((ImageButton) arg0).getId() == R.id.rightMoveBtn) {
                        ((ImageButton)arg0).setImageResource(R.drawable.ic_btn_right_on);
                        mUdpClient.sendBytes(mServerAddr, mServerPort, mRequestRight);
                    }
                    return true;
                }else if(event.getAction() == MotionEvent.ACTION_UP) {
                    if (((ImageButton) arg0).getId() == R.id.forwardMoveBtn) {
                        ((ImageButton)arg0).setImageResource(R.drawable.ic_btn_forward_off);
                        mUdpClient.sendBytes(mServerAddr, mServerPort, mRequestStop);
                    } else if (((ImageButton) arg0).getId() == R.id.backwardMoveBtn) {
                        ((ImageButton)arg0).setImageResource(R.drawable.ic_btn_backward_off);
                        mUdpClient.sendBytes(mServerAddr, mServerPort, mRequestStop);
                    } else if (((ImageButton) arg0).getId() == R.id.leftMoveBtn) {
                        ((ImageButton)arg0).setImageResource(R.drawable.ic_btn_left_off);
                    } else if (((ImageButton) arg0).getId() == R.id.rightMoveBtn) {
                        ((ImageButton)arg0).setImageResource(R.drawable.ic_btn_right_off);
                    }

                    return true;
                }
                return false;
            }
        };

        mBackMoveBtn = (ImageButton)rootView.findViewById(R.id.backwardMoveBtn);
        mBackMoveBtn.setOnTouchListener(listener);
        mForMoveBtn = (ImageButton)rootView.findViewById(R.id.forwardMoveBtn);
        mForMoveBtn.setOnTouchListener(listener);
        mRightMoveBtn = (ImageButton)rootView.findViewById(R.id.rightMoveBtn);
        mRightMoveBtn.setOnTouchListener(listener);
        mLeftMoveBtn = (ImageButton)rootView.findViewById(R.id.leftMoveBtn);
        mLeftMoveBtn.setOnTouchListener(listener);

        try {
            detectorSSD =
                    TFLiteObjectDetectionSSDAPIModel.create(
                            getActivity().getAssets(),
                            "ssdlite_mobilenet_v2_quantized.tflite",
                            "",
                            300,
                            Classifier.Device.CPU,
                            MyConstants.MODEL_TYPE.UINT8,
                            0.5f,
                            1,
                            CamResolution.getWidth(),
                            CamResolution.getHeight()
                    );
            detectorSSD.startThread();
        } catch (final IOException e) {
            Log.e(TAG, "Exception initializing classifier!");
            Toast toast =
                    Toast.makeText(
                            getActivity(), "Classifier could not be initialized", Toast.LENGTH_SHORT);
            toast.show();
        }

        for (int i=0; i<mPoints.length;i++){
            mPoints[i] = new Point(0,0);
        }

        mTrackingOverlay = (OverlayView) rootView.findViewById(R.id.tracking_overlay);
        assert (mTrackingOverlay != null);
//追踪回调 绘制矩形等
        mTrackingOverlay.addCallback(
                new OverlayView.DrawCallback() {
                    @Override
                    public void drawCallback(Canvas canvas) {
                        if (MyConstants.DEBUG) {
                            Rect dstRectForRender = new Rect(0, 0, mTrackingOverlay.getWidth(), mTrackingOverlay.getHeight());
                            Matrix matrix = new Matrix();
                            matrix.postRotate(90);
                            Bitmap scaleBitmap = Bitmap.createScaledBitmap(mBitmapDebug, mTrackingOverlay.getWidth(), mTrackingOverlay.getHeight(), false);
                            Bitmap rotatedBitmap = Bitmap.createBitmap(scaleBitmap, 0, 0, mTrackingOverlay.getWidth(), mTrackingOverlay.getHeight(), matrix, true);
                            canvas.drawBitmap(rotatedBitmap, null, dstRectForRender, null);
                        }
                        if (detectorSSD != null && mObjDet) {
                            int overlayWidth = mTrackingOverlay.getWidth();
                            int overlayHeight = mTrackingOverlay.getHeight();
                            int imgWidth = mBitmapGrab.getWidth();
                            int imgHeight = mBitmapGrab.getHeight();
                            ((TFLiteObjectDetectionSSDAPIModel) detectorSSD).getResult(detectorSSDResult);
                            Paint paint = new Paint();
                            Paint paintText = new Paint();
                            paint.setColor(Color.rgb(0, 255, 0));
                            Log.d(TAG, "Obj cnt: " + detectorSSDResult.size());
                            for (TFLiteObjectDetectionSSDAPIModel.Recognition det : detectorSSDResult) {
                                Log.d(TAG, "processing: " + det);
                                paint.setStrokeWidth(10);
                                paint.setStyle(Paint.Style.STROKE);
                                float left = det.getLocation().left * mTrackingOverlay.getWidth();
                                if (left < 0) {
                                    left = 0;
                                } else if (left > mTrackingOverlay.getWidth()) {
                                    left = mTrackingOverlay.getWidth();
                                }

                                float top = det.getLocation().top * mTrackingOverlay.getHeight();
                                if (top < 0) {
                                    top = 0;
                                } else if (top > mTrackingOverlay.getHeight()) {
                                    top = mTrackingOverlay.getHeight();
                                }

                                float right = det.getLocation().right * mTrackingOverlay.getWidth();
                                ;
                                if (right < 0) {
                                    right = 0;
                                } else if (right > mTrackingOverlay.getWidth()) {
                                    right = mTrackingOverlay.getWidth();
                                }

                                float bottom = det.getLocation().bottom * mTrackingOverlay.getHeight();
                                if (bottom < 0) {
                                    bottom = 0;
                                } else if (bottom > mTrackingOverlay.getHeight()) {
                                    bottom = mTrackingOverlay.getHeight();
                                }
                                paintText.setColor(Color.BLUE);
                                paintText.setStrokeWidth(2);
                                paintText.setStyle(Paint.Style.FILL);
                                paintText.setTextSize(50);
                                canvas.drawRect(left, top, right, bottom, paint);
                                paint.setStyle(Paint.Style.FILL);
                                String txt = det.getTitle();// + "(" + String.format("%.2f", det.getConfidence()) + ")";
                                canvas.drawRect(left, top, left-60, top+txt.length()*30+50, paint);
                                canvas.save();
                                canvas.rotate(90, left-50, top + 50);
                                canvas.drawText(txt, left - 50, top + 50, paintText);
                                canvas.restore();
                            }
                        }

                        if(mSelectedTracker.equals("ObjectTracking") && mStream){
                            if(!mInitTrackObj){
                                String msg1 = "Object is selected by 1 touch and drag following by a";
                                String msg2 = "rectangle, make double touch with another finger to lock";
                                String msg3 = "the object, double touch again to release the tracking object";
                                Paint paintText = new Paint();
                                paintText.setColor(Color.YELLOW);
                                paintText.setStrokeWidth(2);
                                paintText.setStyle(Paint.Style.FILL);
                                paintText.setTextSize(mTrackingOverlay.getWidth()/23);
                                canvas.save();
                                canvas.rotate(90, mTrackingOverlay.getWidth()*10/12, mTrackingOverlay.getHeight()/8);
                                canvas.drawText(msg1, mTrackingOverlay.getWidth()*5/6, mTrackingOverlay.getHeight()/8, paintText);
                                canvas.restore();
                                canvas.save();
                                canvas.rotate(90, mTrackingOverlay.getWidth()*9/12, mTrackingOverlay.getHeight()/8);
                                canvas.drawText(msg2, mTrackingOverlay.getWidth()*9/12, mTrackingOverlay.getHeight()/8, paintText);
                                canvas.restore();
                                canvas.save();
                                canvas.rotate(90, mTrackingOverlay.getWidth()*8/12, mTrackingOverlay.getHeight()/8);
                                canvas.drawText(msg3, mTrackingOverlay.getWidth()*8/12, mTrackingOverlay.getHeight()/8, paintText);
                                canvas.restore();
                                canvas.save();
                            }
                            if(mDrawing != Drawing.CLEAR) {
                                Paint paint = new Paint();
                                paint.setColor(Color.rgb(0, 0, 255));
                                paint.setStrokeWidth(10);
                                paint.setStyle(Paint.Style.STROKE);
                                canvas.drawRect(mPoints[0].x, mPoints[0].y, mPoints[1].x, mPoints[1].y, paint);
                                if (mDrawing == Drawing.TRACKING) {
                                    paint.setColor(Color.rgb(0, 255, 0));
                                    canvas.drawLine((mPoints[0].x + mPoints[1].x) / 2,
                                            0,
                                            (mPoints[0].x + mPoints[1].x) / 2,
                                            mTrackingOverlay.getHeight(),
                                            paint);
                                    canvas.drawLine(0,
                                            (mPoints[0].y + mPoints[1].y) / 2,
                                            mTrackingOverlay.getWidth(),
                                            (mPoints[0].y + mPoints[1].y) / 2,
                                            paint);
                                    paint.setColor(Color.YELLOW);
                                    paint.setStrokeWidth(2);
                                    paint.setStyle(Paint.Style.FILL);
                                    paint.setTextSize(30);
                                    String strX = Integer.toString((mPoints[0].x + mPoints[1].x) / 2) + "/" + Integer.toString(mTrackingOverlay.getWidth());
                                    String strY = Integer.toString((mPoints[0].y + mPoints[1].y) / 2) + "/" + Integer.toString(mTrackingOverlay.getHeight());
                                    canvas.drawText(strX, (mPoints[0].x + mPoints[1].x) / 4, (mPoints[0].y + mPoints[1].y) / 2 - 10, paint);
                                    canvas.save();
                                    canvas.rotate(90, (mPoints[0].x + mPoints[1].x) / 2 + 10, (mPoints[0].y + mPoints[1].y) / 4);
                                    canvas.drawText(strY, (mPoints[0].x + mPoints[1].x) / 2 + 10, (mPoints[0].y + mPoints[1].y) / 4, paint);
                                    canvas.restore();
                                }
                            }
                        }else if(mSelectedTracker.equals("None") && mStream){
                            mInitTrackObj = false;
                            //TODO
                            if(!mInitStream){
                                Paint paintText = new Paint();
                                paintText.setColor(Color.YELLOW);
                                paintText.setStrokeWidth(2);
                                paintText.setStyle(Paint.Style.FILL);
                                paintText.setTextSize(mTrackingOverlay.getWidth()/20);
                                canvas.save();
                                canvas.rotate(90, mTrackingOverlay.getWidth()*5/6, mTrackingOverlay.getHeight()/8);
                                canvas.drawText("Touch upper half screen to move camera up !", mTrackingOverlay.getWidth()*5/6, mTrackingOverlay.getHeight()/8, paintText);
                                canvas.restore();
                                canvas.save();
                                canvas.rotate(90, mTrackingOverlay.getWidth()/6, mTrackingOverlay.getHeight()/8);
                                canvas.drawText("Touch lower half screen to move camera down !", mTrackingOverlay.getWidth()/6, mTrackingOverlay.getHeight()/8, paintText);
                                canvas.restore();
                            }
                        }
                    }
                }
        );
//遥控舵机云台
        mTrackingOverlay.setOnTouchListener(new View.OnTouchListener() {
            @Override
            public boolean onTouch(View view, MotionEvent event) {
                final int X = (int) event.getX();
                final int Y = (int) event.getY();
                Log.d(TAG, ": " + Integer.toString(X) + " " + Integer.toString(Y) );
                mInitStream = true;
                mInitTrackObj = true;
                switch (event.getAction() & MotionEvent.ACTION_MASK) {
                    case MotionEvent.ACTION_UP:
//                            Log.d(TAG, ": " +  "MotionEvent.ACTION_UP" );
                        if (mSelectedTracker.equals("None")) {
                            mUdpClient.sendBytes(mServerAddr, mServerPort, mRequestCamStill);
                            break;
                        }
                        if(!mTargetLocked) {
                            mDrawing = Drawing.CLEAR;
                            mTrackingOverlay.postInvalidate();
                        }
                        break;
                    case MotionEvent.ACTION_POINTER_DOWN:
//                            Log.d(TAG, ": " +  "MotionEvent.ACTION_POINTER_DOWN" );
                        if(mSelectedTracker.equals("ObjectTracking")==false){
                            break;
                        }

                        if (mTargetLocked == false) {
                            if((mPoints[0].x-mPoints[1].x != 0) && (mPoints[0].y-mPoints[1].y != 0)) {
                                mTargetLocked = true;
                                mMatGrab = new Mat();
                                Toast toast = Toast.makeText(getActivity(), "Target is LOCKED !", Toast.LENGTH_LONG);
                                toast.setGravity(Gravity.TOP | Gravity.CENTER, 0, 0);
                                toast.show();
                            }else{
                                mTargetLocked = false;
                            }
                        }else{
                            mTargetLocked = false;
                            Toast toast = Toast.makeText(getActivity(), "Target is UNLOCKED !", Toast.LENGTH_LONG);

                            toast.setGravity(Gravity.TOP | Gravity.CENTER, 0, 0);
                            toast.show();
                        }
                        mDrawing = Drawing.DRAWING;
                        mTrackingOverlay.postInvalidate();
                        break;
                    case MotionEvent.ACTION_POINTER_UP:
//                            Log.d(TAG, ": " +  "MotionEvent.ACTION_POINTER_UP" );
                        break;
                    case MotionEvent.ACTION_DOWN:
//                        Log.d(TAG, ": " +  "MotionEvent.ACTION_DOWN" );
                        if (mSelectedTracker.equals("None")) {

                            if (X < mTrackingOverlay.getWidth() / 3
                                    && Y > mTrackingOverlay.getHeight() / 3 && Y < mTrackingOverlay.getHeight() / 3 * 2) {
                                mUdpClient.sendBytes(mServerAddr, mServerPort, mRequestCamDown);
                            } else if(X > mTrackingOverlay.getWidth() / 3 * 2
                                    && Y > mTrackingOverlay.getHeight() / 3 && Y < mTrackingOverlay.getHeight() / 3 * 2) {
                                mUdpClient.sendBytes(mServerAddr, mServerPort, mRequestCamUp);
                            }
                            else if (X > mTrackingOverlay.getWidth() / 3 && X < mTrackingOverlay.getWidth() / 3 * 2
                                    && Y < mTrackingOverlay.getHeight() / 3 ) {
                                mUdpClient.sendBytes(mServerAddr, mServerPort, mRequestCamLeft);
                            } else if(X > mTrackingOverlay.getWidth() / 3 && X < mTrackingOverlay.getWidth() / 3 * 2
                                    && Y > mTrackingOverlay.getHeight() / 3 * 2){
                                mUdpClient.sendBytes(mServerAddr, mServerPort, mRequestCamRight);
                            }
                            break;
                        }
                        if(!mTargetLocked && mSelectedTracker.equals("ObjectTracking")) {
                            mDrawing = Drawing.DRAWING;
                            mPoints[0].x = X;
                            mPoints[0].y = Y;
                            mPoints[1].x = X;
                            mPoints[1].y = Y;
                            mTrackingOverlay.postInvalidate();
                        }
                        break;
                    case MotionEvent.ACTION_MOVE:
//                            Log.d(TAG, ": " +  "MotionEvent.ACTION_MOVE" );
                        if(!mTargetLocked && mSelectedTracker.equals("ObjectTracking")) {
                            mPoints[1].x = X;
                            mPoints[1].y = Y;
                            mTrackingOverlay.postInvalidate();
                        }
                        break;
                }
//                if(mTargetLocked==true){
//                    getView().findViewById(R.id.objTrackBtn).setEnabled(false);
//                }else{
//                    getView().findViewById(R.id.objTrackBtn).setEnabled(true);
//                }
                return true;
            }
        });

        return rootView;
    }

    private void connectWebSocket() {
        URI uri;
        try {
            uri = new URI("ws://"+mServerExactAddress+":86/");
        } catch (URISyntaxException e) {
            e.printStackTrace();
            return;
        }

        mWebSocketClient = new WebSocketClient(uri) {
            @Override
            public void onOpen(ServerHandshake serverHandshake) {
                Log.d("Websocket", "Open");
            }

            @Override
            public void onClose(int i, String s, boolean b) {
                Log.d("Websocket", "Closed " + s);
            }

            @Override
            public void onMessage(String message){
                Log.d("Websocket", "Receive");
            }
//视频流接收
            @Override
            public void onMessage(ByteBuffer message){
//                Log.d("Websocket", "Receive");
                getActivity().runOnUiThread(new Runnable() {
                    @Override
                    public void run() {
                        byte[] imageBytes= new byte[message.remaining()];
                        message.get(imageBytes);
                        final Bitmap bmp=BitmapFactory.decodeByteArray(imageBytes,0,imageBytes.length);
                        if (bmp == null)
                        {
                            return;
                        }
                        int viewWidth = mServerImageView.getWidth();
                        Matrix matrix = new Matrix();
                        matrix.postRotate(90);
                        final Bitmap bmp_traspose = Bitmap.createBitmap(bmp, 0, 0, bmp.getWidth(), bmp.getHeight(), matrix, true );
                        float imagRatio = (float)bmp_traspose.getHeight()/(float)bmp_traspose.getWidth();
                        int dispViewH = (int)(viewWidth*imagRatio);
                        mServerImageView.setImageBitmap(Bitmap.createScaledBitmap(bmp_traspose, viewWidth, dispViewH, false));

                        mBitmapGrab = bmp;
                        mProcessing = detectorSSD.IsProcessing;
                        if (!mProcessing) {
                            processing();
                        }
                    }
                });
            }

            @Override
            public void onError(Exception e) {
                Log.d("Websocket", "Error " + e.getMessage());
            }
        };
        mWebSocketClient.connect();
    }

    private void trackingDlg(){
        AlertDialog.Builder builder = new AlertDialog.Builder(getActivity());
        builder.setTitle("Tracker Selection");

        final RadioButton[] rb = new RadioButton[mRadioBtnNames.length];
        RadioGroup rg = new RadioGroup(getActivity()); //create the RadioGroup
        rg.setOrientation(RadioGroup.VERTICAL);

        for(int i=0; i < mRadioBtnNames.length; i++){
            rb[i]  = new RadioButton(getActivity());
            rb[i].setText(" " + mRadioBtnNames[i]);
            rb[i].setId(i + 100);
            rg.addView(rb[i]);
            if(mRadioBtnNames[i].equals(mSelectedTracker)){
                rb[i].setChecked(true);
            }
        }

        // This overrides the radiogroup onCheckListener
        rg.setOnCheckedChangeListener(new RadioGroup.OnCheckedChangeListener()
        {
            public void onCheckedChanged(RadioGroup group, int checkedId){
                // This will get the radiobutton that has changed in its check state
                RadioButton checkedRadioButton = (RadioButton)group.findViewById(checkedId);
                // This puts the value (true/false) into the variable
                boolean isChecked = checkedRadioButton.isChecked();
                if (isChecked)
                {
                    // Changes the textview's text to "Checked: example radiobutton text"
                    int i = 0;
                    for( i = 0; i < mRadioBtnNames.length; i++) {
                        if(checkedRadioButton.getText().toString().replace(" ", "").equals(mRadioBtnNames[i])){
                            break;
                        }
                    }
                    mRadioIndex = i;
                }
            }
        });

        LinearLayout lay = new LinearLayout(getActivity());
        lay.setOrientation(LinearLayout.VERTICAL);
        lay.setPadding(0,30,0,0);
        lay.setGravity(Gravity.CENTER_HORIZONTAL);
        lay.addView(rg);


        builder.setView(lay);

        // Set up the buttons
        builder.setPositiveButton("OK", new DialogInterface.OnClickListener() {
            @Override
            public void onClick(DialogInterface dialog, int which) {

                mSelectedTracker = mRadioBtnNames[mRadioIndex];

                if (mSelectedTracker.equals("ObjectTracking")) {
                    ((Button) getActivity().findViewById(R.id.objTrackBtn)).setBackgroundResource(R.drawable.my_button_bg_2);
                    ((Button) getActivity().findViewById(R.id.objTrackBtn)).setTextColor(Color.rgb(0,0,255));
                    mUdpClient.sendBytes(mServerAddr, mServerPort, ObjectTrackingOn);
                } else if (mSelectedTracker.equals("LaneTracking")) {
                    ((Button) getActivity().findViewById(R.id.objTrackBtn)).setBackgroundResource(R.drawable.my_button_bg_2);
                    ((Button) getActivity().findViewById(R.id.objTrackBtn)).setTextColor(Color.rgb(0,0,255));
                    mUdpClient.sendBytes(mServerAddr, mServerPort, LaneTrackingOn);
                } else {
                    ((Button) getActivity().findViewById(R.id.objTrackBtn)).setBackgroundResource(R.drawable.my_button_bg);
                    ((Button) getActivity().findViewById(R.id.objTrackBtn)).setTextColor(Color.rgb(255,255,255));
                    mUdpClient.sendBytes(mServerAddr, mServerPort, mRequestStop);
                }
            }
        });


        builder.setCancelable(false);
        Dialog dialog = builder.show();
    }
//物体追踪
    private void processing() {
        int overlayWidth = mTrackingOverlay.getWidth();
        int overlayHeight = mTrackingOverlay.getHeight();
        mRadiusCircle = 0;

        if(mObjDet) {
            if (MyConstants.DEBUG) {
                detectorSSD.setBitmap(mBitmapDebug);
            } else {
                detectorSSD.setBitmap(mBitmapGrab);
            }
        }

        if(mTargetLocked && mSelectedTracker.equals("ObjectTracking")) {
            Utils.bitmapToMat(mBitmapGrab, mMatGrab);
            org.opencv.imgproc.Imgproc.resize(mMatGrab, mMatGrab, new org.opencv.core.Size(320,240));
            org.opencv.imgproc.Imgproc.cvtColor(mMatGrab, mMatGrab, Imgproc.COLOR_RGBA2BGR);

            if(mDrawing==Drawing.DRAWING) {

                int imgWidth = mMatGrab.cols();
                int imgHeight = mMatGrab.rows();

                int x0 = mPoints[0].y;
                int y0 = overlayWidth - mPoints[0].x;
                int x1 = mPoints[1].y;
                int y1 = overlayWidth - mPoints[1].x;

                int minX = (int)((float)Math.min(x0, x1)/overlayHeight*mMatGrab.cols());
                int minY = (int)((float)Math.min(y0, y1)/overlayWidth*mMatGrab.rows());
                int maxX = (int)((float)Math.max(x0, x1)/overlayHeight*mMatGrab.cols());
                int maxY = (int)((float)Math.max(y0, y1)/overlayWidth*mMatGrab.rows());

                mInitRectangle = new org.opencv.core.Rect2d(minX, minY, maxX-minX, maxY-minY);
                mMatGrabInit = new Mat();
                mMatGrab.copyTo(mMatGrabInit);

                if(mSelectedTracker.equals("TrackerMedianFlow")) {
                    mTracker = TrackerMedianFlow.create();
                }else if(mSelectedTracker.equals("TrackerCSRT")||mSelectedTracker.equals("ObjectTracking")) {
                    mTracker = TrackerCSRT.create();
                }else if(mSelectedTracker.equals("TrackerKCF")) {
                    mTracker = TrackerKCF.create();
                }else if(mSelectedTracker.equals("TrackerMOSSE")) {
                    mTracker = TrackerMOSSE.create();
                }else if(mSelectedTracker.equals("TrackerTLD")) {
                    mTracker = TrackerTLD.create();
                }else if(mSelectedTracker.equals("TrackerMIL")) {
                    mTracker = TrackerMIL.create();
                }

                mTracker.init(mMatGrabInit, mInitRectangle);
                mDrawing = Drawing.TRACKING;


            }else{
                org.opencv.core.Rect2d trackingRectangle = new org.opencv.core.Rect2d(0, 0, 1,1);
                mTracker.update(mMatGrab, trackingRectangle);

                mPoints[1].x = overlayWidth - (int)(trackingRectangle.y*(float)overlayWidth/(float)mMatGrab.rows());
                mPoints[0].y = (int)(trackingRectangle.x*(float)mTrackingOverlay.getHeight()/(float)mMatGrab.cols());
                mPoints[0].x = mPoints[1].x - (int)(trackingRectangle.height*(float)mTrackingOverlay.getWidth()/(float)mMatGrab.rows());
                mPoints[1].y = mPoints[0].y +(int)(trackingRectangle.width*(float)mTrackingOverlay.getHeight()/(float)mMatGrab.cols());

                int centerX = (mPoints[0].x+mPoints[1].x)/2;
                int centerY = (mPoints[0].y+mPoints[1].y)/2;

                if(centerX-mTrackingOverlay.getWidth()/2 > 150){
                    count ++;
                    if(count > 20) {
                        mUdpClient.sendBytes(mServerAddr, mServerPort, mRequestCamUp);
                        count  = 0;
                    }
                }else if(centerX-mTrackingOverlay.getWidth()/2 < -150){
                    count ++;
                    if(count > 20) {
                        mUdpClient.sendBytes(mServerAddr, mServerPort, mRequestCamDown);
                        count  = 0;
                    }
                }

                if(centerY-mTrackingOverlay.getHeight()/2 > 200){
                    count ++;
                    if(count > 20) {
                        mUdpClient.sendBytes(mServerAddr, mServerPort, mRequestCamLeft);
                        count  = 0;
                    }
                }else if(centerY-mTrackingOverlay.getHeight()/2 < -200){
                    count ++;
                    if(count > 20) {
                        mUdpClient.sendBytes(mServerAddr, mServerPort, mRequestCamRight);
                        count  = 0;
                    }
                }
                mTrackingOverlay.postInvalidate();
            }
        }else{

            if (mTracker != null) {
                mTracker.clear();
                mTracker = null;
            }
        }
        mTrackingOverlay.invalidate();
    }

    public void showAdressDialog(Context context) {
        AlertDialog.Builder alertDialog = new AlertDialog.Builder(context);
        View view1 = View.inflate(context, R.layout.adress_dialog, null);
        TextView et = view1.findViewById(R.id.text_adress);
        VerticalButton bu = view1.findViewById(R.id.btn_set);
        alertDialog
                .setView(view1)
                .create();
        AlertDialog show = alertDialog.show();
        // 设置对话框的宽度和高度
        Window window = show.getWindow();
        if (window != null) {
            WindowManager.LayoutParams layoutParams = new WindowManager.LayoutParams();
            layoutParams.copyFrom(window.getAttributes());
            layoutParams.width = WindowManager.LayoutParams.WRAP_CONTENT; // 设置宽度为自适应内容
            layoutParams.height = WindowManager.LayoutParams.WRAP_CONTENT; // 设置高度为自适应内容
            layoutParams.gravity = Gravity.CENTER;
            window.setAttributes(layoutParams);
        }
        bu.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View view) {
                mServerAddressBroadCast = et.getText().toString().trim();
                show.dismiss();
            }
        });
    }
//MQTT接收
    public void Get() {
        new Thread(new Runnable() {
            @Override
            public void run() {
                while (true) {
                    try {
                        OkHttpClient client = new OkHttpClient();
                        //http(s)://iot-api.heclouds.com/thingmodel/query-device-property?product_id=w50WLDzGBb&device_name=light
                        //http://iot-api.heclouds.com/thingmodel/query-thing-model?product_id=w50WLDzGBb
                        Request request = new Request.Builder().url("https://iot-api.heclouds.com/thingmodel/query-device-property?product_id=2KYi18U9v7&device_name=test")
                                .header("Authorization",
                                        "version=2020-05-29&res=userid%2F344889&et=1956499200&method=sha1&sign=ecPB8V42DVCvuWzr464k7wdx60g%3D")
                                .build();
                        Response response = client.newCall(request).execute();
                        String responseData = response.body().string();
                        JsonRootBean app = new Gson().fromJson(responseData, JsonRootBean.class);

                        Co2 = app.data.get(0).value.toString()+" ppm";
                        Voc = app.data.get(1).value.toString()+" ppm";
                        Temp = app.data.get(3).value.toString()+" ℃";
                        Humi = app.data.get(2).value.toString()+" ％";

                    } catch (IOException e) {
                        e.printStackTrace();
                    }
                    try {
                        Thread.sleep(1000);
                    } catch (InterruptedException e) {
                        throw new RuntimeException(e);
                    }//延时一秒获取一次亮度
                }
            }
        }).start();
    }

    public void onDestroy() {
        Log.e(TAG, "onDestroy");
        detectorSSD.requestStop();
        detectorSSD.waitForExit();
        mWebSocketClient.close();
        super.onDestroy();
    }

}
